package cn.wolfcode.wolf2w.service.impl;

import cn.wolfcode.wolf2w.domain.Destination;
import cn.wolfcode.wolf2w.domain.Travel;
import cn.wolfcode.wolf2w.domain.UserInfo;
import cn.wolfcode.wolf2w.exception.LogicException;
import cn.wolfcode.wolf2w.query.TravelQuery;
import cn.wolfcode.wolf2w.redis.service.ITravelRedisService;
import cn.wolfcode.wolf2w.redis.vo.TravelStatisVo;
import cn.wolfcode.wolf2w.repository.TravelRepository;
import cn.wolfcode.wolf2w.service.IDestinationService;
import cn.wolfcode.wolf2w.service.ITravelService;
import cn.wolfcode.wolf2w.service.IUserInfoService;
import cn.wolfcode.wolf2w.util.PageUtils;
import cn.wolfcode.wolf2w.vo.TravelCondition;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;

@Service
public class TravelServiceImpl implements ITravelService {
	@Autowired
	private TravelRepository travelRepository;
	@Autowired
	private MongoTemplate template;
	@Autowired
	private IUserInfoService userInfoService;
	@Autowired
	private IDestinationService destinationService;
	@Autowired
	private ITravelRedisService travelRedisService;

	@Override
	public void save(Travel travel) {
		travel.setId(null);
		travelRepository.save(travel);
	}

	@Override
	public void update(Travel travel) {
		travelRepository.save(travel);
	}

	@Override
	public void delete(String id) {
		travelRepository.deleteById(id);
	}

	@Override
	public Travel get(String id) {
		Travel travel = null;
		if (StringUtils.hasLength(id)) {
			travel = travelRepository.findById(id).orElse(null);
			travel.setDest(destinationService.get(travel.getDestId()));
			travel.setAuthor(userInfoService.get(travel.getUserId()));
		}
		return travel;
	}

	@Override
	public List<Travel> list() {
		return travelRepository.findAll();
	}

	@Override
	public Page<Travel> query(TravelQuery qo, UserInfo userInfo) {
		Query query = new Query();
		Page<Travel> page;
		// 后台
		if (!StringUtils.hasLength(qo.getStatus())) {
			query.addCriteria(Criteria.where("state").is(qo.getState()));

			// 查看待审核
//			if (qo.getState() == -1) {
//				query.addCriteria(Criteria.where("state").is(Travel.STATE_REJECT));
//			} else if (qo.getState() == 1) {    //查看审核拒绝
//				query.addCriteria(Criteria.where("state").is(Travel.STATE_WAITING));
//			}  else if (qo.getState() == 2) {    //查看审核拒绝
//				query.addCriteria(Criteria.where("state").is(Travel.STATE_RELEASE));
//			}
			page = PageUtils.page(template, query, Travel.class, qo, null);
		} else {    // 前端
			Sort sort = null;
			if(StringUtils.hasLength(qo.getDestId())){
				query.addCriteria(Criteria.where("destId").is(qo.getDestId()));
			}
			// 最新或最热排序
			if (qo.getOrderType() == 1) {
				sort = Sort.by(Sort.Direction.DESC, "releaseTime");
			} else if (qo.getOrderType() == 2) {
				sort = Sort.by(Sort.Direction.DESC, "viewnum");
			}
			// 按照天数来查询
			if (qo.getDayType() > 0) {
				query.addCriteria(Criteria.where("day").
						gte(TravelCondition.getDay(qo.getDayType()).getMin()).
						lte(TravelCondition.getDay(qo.getDayType()).getMax()));
			}
			// 按照人均费用查询
			if (qo.getPerExpendType() > 0) {
				query.addCriteria(Criteria.where("perExpend").
						gte(TravelCondition.getPerExpend(qo.getPerExpendType()).getMin()).
						lte(TravelCondition.getPerExpend(qo.getPerExpendType()).getMax()));
			}
			// 只看公开的并且发布的
			Criteria criteria = new Criteria().andOperator(
					Criteria.where("state").is(Travel.STATE_RELEASE),
					Criteria.where("isPublic").is(Travel.ISPUBLIC_YES));
			// 自己的所有 或者 公开的并且发布的
			if (userInfo != null) {
				query.addCriteria(new Criteria()
						.orOperator(Criteria.where("userId").is(userInfo.getId()),criteria));
			} else {
				query.addCriteria(criteria);
			}
			page = PageUtils.page(template, query, Travel.class, qo, sort);
		}

		// 往里面游记设置作者对象
		for (Travel travel : page.getContent()) {
			travel.setAuthor(userInfoService.get(travel.getUserId()));
		}
		return page;
	}

	@Override
	public void changeState(String id, int state) {
		Travel travel = this.get(id);
		// 游记为空或不是待发布
		if (travel == null) {
			throw new LogicException("参数异常");
		}
		// 当前游记是待发布状态
		if (travel.getState() == Travel.STATE_WAITING) {    // 1
			// 传过来的状态是发布
			if (Travel.STATE_RELEASE == state) {    // 2
				travel.setState(state);
				travel.setLastUpdateTime(new Date());
			} else if (Travel.STATE_REJECT == state) {        // 3,传过来的状态是拒绝
				travel.setState(state);
			}
		} else {
			// 当前游记是已发布状态才下架
			if (travel.getState() == Travel.STATE_RELEASE) {        // 3
				// 下架
				travel.setState(state);
			}
		}
		this.update(travel);
	}

	@Override
	public void saveOrUpdate(Travel travel) {
		// 维护丢失数据
		Destination destination = destinationService.get(travel.getDestId());
		// 目的地名字
		travel.setDestName(destination.getName());

		if (StringUtils.hasLength(travel.getId())) {
			Travel temp = this.get(travel.getId());
			// 维护创建时间
			travel.setCreateTime(temp.getCreateTime());
			// 维护发布时间
			travel.setReleaseTime(temp.getReleaseTime());
			// 维护最后更新时间
			travel.setLastUpdateTime(new Date());
			// 维护点击数,回复数,收藏数,分享数,点赞数
			travel.setViewnum(temp.getViewnum());
			travel.setReleaseTime(temp.getReleaseTime());
			travel.setFavornum(temp.getFavornum());
			travel.setSharenum(temp.getSharenum());
			travel.setThumbsupnum(temp.getThumbsupnum());
			this.update(travel);
		} else {
			// 创建时间
			travel.setCreateTime(new Date());
			this.save(travel);
		}
	}

	@Override
	public List<Travel> queryByViewnum(String destId) {
		Query query = new Query();

		Pageable pageable ;
		if(StringUtils.hasLength(destId)){
			// 分页三条,显示第一页,按 viewnum 逆序排序
			pageable = PageRequest.of(0, 3, Sort.by(Sort.Direction.DESC, "viewnum"));
			query.addCriteria(Criteria.where("destId").is(destId));
		}else {
			pageable = PageRequest.of(0, 3, Sort.by(Sort.Direction.DESC, "viewnum"));
		}

		query.addCriteria(Criteria.where("state").is(Travel.STATE_RELEASE));
		query.with(pageable);
		return template.find(query, Travel.class);
	}

	@Override
	public boolean strategyThumbup(String tid, String uid) {

		return travelRedisService.travelThumbup(tid,uid);
	}

	@Override
	public TravelStatisVo travelsVo(String tid) {
		travelRedisService.viewnumIncreas(tid);
		return travelRedisService.getTravelStatisVo(tid);
	}

	@Override
	public boolean travelFavor(String tid, String uid) {
		travelRedisService.favornumIncreas(tid,uid);
		return false;
	}

	// 获取某个用户的收藏列表
	@Override
	public List<String> getTravelsFavor(String userId) {
		return travelRedisService.getUserFavorList(userId);
	}

	@Override
	public void updateTravelVo(TravelStatisVo vo) {
		Travel travel = this.get(vo.getTravelId());
		BeanUtils.copyProperties(vo, travel);
		this.update(travel);
	}

	@Override
	public List<Travel> findByDestName(String destName) {
		return travelRepository.findByDestName(destName);
	}
}
